package com.example.redisstudy.redisCache.config;

import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.Arrays;

/**
 * @classDesc: 功能描述: 更改RedisTemplate的序列化器
 * @author: 李明杰
 * @date: 2021/11/19 16:53
 * @copyright
 */
@Configuration
public class MyRedisConfig {

    /**
     * 自定义key生成策略
     *
     * @return
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> method.getName() + "[" + Arrays.asList(params) + "]";
    }

    /**
     * "缓存"使用JSON序列化器【SpringBoot 2.x版本】
     * 新版写法在评论区： https://www.bilibili.com/video/BV1KW411F7oX?p=12
     * <p>
     * RedisCacheConfiguration配置类中，可以链式编程设置自己想要的属性，例如：
     * 配置类中默认使用了前缀，下面例子中可以使用config.disableKeyPrefix()取消默认使用前缀。
     * （没有set方法，要看源码）
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 使用缓存的默认配置（config可以链式编程，设置自己想要的的属性）
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 使用 Jackson2JsonRedisSerializer 作为序列化器
        config = config.serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                        new Jackson2JsonRedisSerializer(Object.class)));
        RedisCacheManager.RedisCacheManagerBuilder builder =
                RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config);

        return builder.build();
    }

    /**
     * 对RedisTemplate序列号设置
     * 注意：key如果也设置为JSON序列化器，会带上引号！！
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);

        // Hash的key也采用StringRedisSerializer的序列化方式
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        return redisTemplate;

    }


}
